/**
* Licensed to the Austrian Association for Software Tool Integration (AASTI)
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. The AASTI licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openengsb.core.common.remote;
import java.util.List;
import java.util.Map;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;
import javax.xml.transform.dom.DOMResult;
import org.apache.commons.lang.ClassUtils;
import org.openengsb.core.api.remote.FilterAction;
import org.openengsb.core.api.remote.FilterException;
import org.openengsb.core.api.remote.MethodCallMessage;
import org.openengsb.core.api.remote.MethodResult;
import org.openengsb.core.api.remote.MethodResultMessage;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
/**
* This filter takes a {@link MethodCallMessage} and serializes it into a {@link Document}. The document is then passed
* to the next filter. The resulting document is then deseralized and returned.
*
* This filter is intended for outgoing ports.
*
* <code>
* <pre>
* [MethodCallMessage] > Filter > [org.w3c.dom.Document] > ...
* |
* v
* [MethodResultMessage] < Filter < [org.w3c.dom.Document] < ...
* </pre>
* </code>
*/
public class XmlMethodCallMarshalOutgoingFilter extends
AbstractFilterChainElement<MethodCallMessage, MethodResultMessage> {
private FilterAction next;
private Unmarshaller unmarshaller;
public XmlMethodCallMarshalOutgoingFilter() {
try {
JAXBContext context = JAXBContext.newInstance(MethodCallMessage.class, MethodResultMessage.class);
unmarshaller = context.createUnmarshaller();
} catch (JAXBException e) {
throw new IllegalStateException(e);
}
}
@Override
protected MethodResultMessage doFilter(MethodCallMessage input, Map<String, Object> metaData)
throws FilterException {
Document serializeRequest = serializeRequest(input);
Document resultDocument = (Document) next.filter(serializeRequest, metaData);
try {
return parseMethodResult(resultDocument);
} catch (JAXBException e) {
throw new FilterException(e);
}
}
private Document serializeRequest(MethodCallMessage result) {
DOMResult domResult = new DOMResult();
try {
@SuppressWarnings("unchecked")
List<Class<?>> classes = ClassUtils.convertClassNamesToClasses(result.getMethodCall().getClasses());
if (classes.contains(null)) {
throw new FilterException("Could not load all required classes. Require: "
+ result.getMethodCall().getClasses() + " got: " + classes);
}
classes.add(MethodCallMessage.class);
JAXBContext jaxbContext =
JAXBContext.newInstance(classes.toArray(new Class<?>[classes.size()]));
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.marshal(new JAXBElement<MethodCallMessage>(new QName(MethodCallMessage.class.getSimpleName()),
MethodCallMessage.class, result), domResult);
} catch (JAXBException e) {
throw new FilterException(e);
}
return (Document) domResult.getNode();
}
private MethodResultMessage parseMethodResult(Document input) throws JAXBException {
MethodResultMessage request = unmarshaller.unmarshal(input, MethodResultMessage.class).getValue();
MethodResult result = request.getResult();
Class<?> resultClass;
try {
resultClass = Class.forName(result.getClassName());
} catch (ClassNotFoundException e) {
throw new FilterException(e);
}
JAXBContext jaxbContext = JAXBContext.newInstance(MethodResult.class, resultClass);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Object parsedArg = unmarshaller.unmarshal((Node) result.getArg(), resultClass).getValue();
result.setArg(parsedArg);
return request;
}
@Override
public void setNext(FilterAction next) {
checkNextInputAndOutputTypes(next, Document.class, Document.class);
this.next = next;
}
}